﻿using OPTSDK_Net;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;

namespace Camera
{
    public class CameraOPT : CameraBase
    {
        private const int DEFAULT_INTERVAL = 40;

        private MyCamera cam;
        private string camStr;
        private OPTDefine.OPT_ConnectCallBack pConnectCallBack;
        private OPTDefine.OPT_FrameCallBack frameCallBack;
        private bool g_isMainThreadExit;
        private Stopwatch m_stopWatch;

        public override event ReadImageDelegate ReadImageEvent;
        public override event ConnectLossDelegate ConnectLossEvent;

        public CameraOPT()
        {
            cam = new MyCamera();
            m_stopWatch = new Stopwatch();
            m_stopWatch.Start();
        }

        public static string[] DeviceListAcq()
        {
            //枚举设备
            // Discover device
            OPTDefine.OPT_DeviceList deviceList = new OPTDefine.OPT_DeviceList();
            OPTDefine.OPT_EInterfaceType interfaceTp = OPTDefine.OPT_EInterfaceType.interfaceTypeAll;
            int res = MyCamera.OPT_EnumDevices(ref deviceList, (uint)interfaceTp);
            if (res != OPTDefine.OPT_OK)
            {
                return null;
            }
            if (deviceList.nDevNum < 1)
            {
                return null;
            }

            // 打印设备基本信息
            // Print device info 
            return DisplayDeviceInfo(deviceList);
        }

        #region 展示设备列表

        private static string[] DisplayDeviceInfo(OPTDefine.OPT_DeviceList deviceInfoList)
        {
            string[] cameraKeys = new string[deviceInfoList.nDevNum];
            for (int i = 0; i < deviceInfoList.nDevNum; i++)
            {
                OPTDefine.OPT_DeviceInfo deviceInfo = (OPTDefine.OPT_DeviceInfo)Marshal.PtrToStructure(deviceInfoList.pDevInfo + Marshal.SizeOf(typeof(OPTDefine.OPT_DeviceInfo)) * i, typeof(OPTDefine.OPT_DeviceInfo));
                // 设备ID信息
                // Device ID
                cameraKeys[i] = deviceInfo.cameraKey;
            }
            return cameraKeys;
        }

        #endregion

        public override bool Open(string camStr)
        {
            this.camStr = camStr;

            // 创建设备句柄
            // Create Device Handle
            int res = cam.OPT_CreateHandle(OPTDefine.OPT_ECreateHandleMode.modeByCameraKey, cameraStr: camStr);
            if (res != OPTDefine.OPT_OK)
            {
                // 销毁设备句柄
                // Destroy Device Handle
                cam.OPT_DestroyHandle();
                return false;
            }

            // 打开相机设备 
            // Connect to camera 
            res = cam.OPT_Open();
            if (res != OPTDefine.OPT_OK)
            {
                cam.OPT_DestroyHandle();
                return false;
            }

            // 设置ChunkData配置
            // Set ChunkData config 
            //res = setChunkDataConf();
            //if (res != OPTDefine.OPT_OK)
            //{
            //    cam.OPT_DestroyHandle();
            //    return false;
            //}

            // 设置相机对sdk命令的响应超时时间, 仅限Gige设备使用(单位：ms)
            // Set the response timeout interval of camera sends command to the API. Only for Gige device(unit：ms)
            res = cam.OPT_GIGE_SetAnswerTimeout(1000);
            if (res != OPTDefine.OPT_OK)
            {
                cam.OPT_DestroyHandle();
                return false;
            }

            // 设置驱动包间隔时间,仅对Gige设备有效(单位：ms)
            // SSet packet timeout, only for Gige device(unit：ms)
            res = cam.OPT_GIGE_SetInterPacketTimeout(50);
            if (res != OPTDefine.OPT_OK)
            {
                cam.OPT_DestroyHandle();
                return false;
            }

            // 设置单次重传最大包个数,仅对GigE设备有效
            // Set the single resend maximum packet number, only for Gige device
            res = cam.OPT_GIGE_SetSingleResendMaxPacketNum(50);
            if (res != OPTDefine.OPT_OK)
            {
                cam.OPT_DestroyHandle();
                return false;
            }

            // 设置同一帧最大丢包的数量,仅对GigE设备有效
            // Set the maximum lost packet number, only for Gige device
            res = cam.OPT_GIGE_SetMaxLostPacketNum(80);
            if (res != OPTDefine.OPT_OK)
            {
                cam.OPT_DestroyHandle();
                return false;
            }

            // 设备连接状态事件回调函数
            // Device connection status event callback function
            pConnectCallBack = OnDeviceLinkNotify;
            res = cam.OPT_SubscribeConnectArg(pConnectCallBack, IntPtr.Zero);
            if (res != OPTDefine.OPT_OK)
            {
                cam.OPT_DestroyHandle();
                return false;
            }

            // 注册数据帧回调函数
            // Register data frame callback function
            frameCallBack = OnGetFrame;
            res = cam.OPT_AttachGrabbing(frameCallBack, IntPtr.Zero);
            if (res != OPTDefine.OPT_OK)
            {
                cam.OPT_DestroyHandle();
                return false;
            }

            //设置缓存个数为8
            //set buffer count to 8
            cam.OPT_SetBufferCount(8);

            return true;
        }

        private int setChunkDataConf()
        {
            int res = OPTDefine.OPT_OK;
            OPTDefine.OPT_DeviceInfo deviceInfo = new OPTDefine.OPT_DeviceInfo();

            // 获取设备信息
            // Get device information
            res = cam.OPT_GetDeviceInfo(ref deviceInfo);
            if (res != OPTDefine.OPT_OK)
            {
                Console.WriteLine("Get device info failed! ErrorCode[{0}]", res);
                return res;
            }

            if (deviceInfo.nCameraType != OPTDefine.OPT_ECameraType.typeGigeCamera &&
                deviceInfo.nCameraType != OPTDefine.OPT_ECameraType.typeU3vCamera)
            {
                Console.WriteLine("CameraType is not support");
                return OPTDefine.OPT_NOT_SUPPORT;
            }

            // 设置CounterSelector
            // Set CounterSelector
            res = cam.OPT_SetEnumFeatureSymbol("CounterSelector", "Counter0");
            if (res != OPTDefine.OPT_OK)
            {
                Console.WriteLine("Set CounterSelector value failed! ErrorCode[{0}]", res);
                return res;
            }

            // 设置CounterResetSource
            // Set CounterResetSource
            res = cam.OPT_SetEnumFeatureSymbol("CounterResetSource", "SoftwareSignal0");
            if (res != OPTDefine.OPT_OK)
            {
                Console.WriteLine("Set CounterResetSource value failed! ErrorCode[{0}]", res);
                return res;
            }

            // 执行CounterReset
            // Execute CounterReset
            res = cam.OPT_ExecuteCommandFeature("CounterReset");
            if (res != OPTDefine.OPT_OK)
            {
                Console.WriteLine("Execute CounterReset failed! ErrorCode[{0}]", res);
                return res;
            }

            // 设置CounterResetSource
            // Set CounterResetSource
            res = cam.OPT_SetEnumFeatureSymbol("CounterResetSource", "SoftwareSignal0");
            if (res != OPTDefine.OPT_OK)
            {
                Console.WriteLine("Set CounterResetSource value failed! ErrorCode[{0}]", res);
                return res;
            }

            // 设置CounterResetSource
            // Set CounterResetSource
            res = cam.OPT_SetEnumFeatureSymbol("CounterResetSource", "Off");
            if (res != OPTDefine.OPT_OK)
            {
                Console.WriteLine("Set CounterResetSource value failed! ErrorCode[{0}]", res);
                return res;
            }

            if (deviceInfo.nCameraType == OPTDefine.OPT_ECameraType.typeGigeCamera)
            {
                // 设置GevGVSPExtendedIDMode
                // Set GevGVSPExtendedIDMode
                res = cam.OPT_SetEnumFeatureSymbol("GevGVSPExtendedIDMode", "On");
                if (res != OPTDefine.OPT_OK)
                {
                    Console.WriteLine("Set GevGVSPExtendedIDMode value failed! ErrorCode[{0}]", res);
                    return res;
                }
            }

            // 设置ChunkModeActive
            // Set ChunkModeActive
            res = cam.OPT_SetBoolFeatureValue("ChunkModeActive", true);
            if (res != OPTDefine.OPT_OK)
            {
                Console.WriteLine("Set ChunkModeActive value failed! ErrorCode[{0}]", res);
                return res;
            }

            // 设置ChunkSelector
            // Set ChunkSelector
            res = cam.OPT_SetEnumFeatureSymbol("ChunkSelector", "Counter0Value");
            if (res != OPTDefine.OPT_OK)
            {
                Console.WriteLine("Set ChunkSelector value failed! ErrorCode[{0}]", res);
                return res;
            }

            // 设置ChunkEnable
            // Set ChunkEnable
            res = cam.OPT_SetBoolFeatureValue("ChunkEnable", true);
            if (res != OPTDefine.OPT_OK)
            {
                Console.WriteLine("Set ChunkEnable value failed! ErrorCode[{0}]", res);
                return res;
            }
            return res;
        }

        // 连接事件通知回调函数
        // Connect event notify callback function
        private void OnDeviceLinkNotify(ref OPTDefine.OPT_SConnectArg pConnectArg, IntPtr pUser)
        {
            // 断线通知
            // offLine notify 
            if (OPTDefine.OPT_EVType.offLine == pConnectArg.EvType)
            {
                DeviceOffLine();
                ConnectLossEvent("相机 " + camStr + " 异常掉线，重新连接中。。。");
            }
            // 上线通知
            // onLine notify 
            else if (OPTDefine.OPT_EVType.onLine == pConnectArg.EvType)
            {
                DeviceOnLine();
            }
        }

        // 断线通知处理
        // offLine notify processing
        private void DeviceOffLine()
        {
            // 停止拉流 
            // Stop grabbing 
            cam.OPT_StopGrabbing();
        }

        // 上线通知处理
        // onLine notify processing
        private void DeviceOnLine()
        {
            int res = OPTDefine.OPT_OK;

            // 关闭相机
            // Close camera 
            cam.OPT_Close();

            do
            {
                if (g_isMainThreadExit)
                {
                    return;
                }

                res = cam.OPT_Open();
                if (res == OPTDefine.OPT_OK)
                {
                    break;
                }

                Thread.Sleep(500);
            } while (true);


            // 重新设备连接状态事件回调函数
            // Device connection status event callback function again 
            pConnectCallBack = OnDeviceLinkNotify;
            cam.OPT_SubscribeConnectArg(pConnectCallBack, IntPtr.Zero);


            // 重新注册数据帧回调函数
            // Register data frame callback function again
            frameCallBack = OnGetFrame;
            cam.OPT_AttachGrabbing(frameCallBack, IntPtr.Zero);

            // 开始拉流 
            // Start grabbing 
            cam.OPT_StartGrabbing();
        }

        // 数据帧回调函数
        // Data frame callback function
        private void OnGetFrame(ref OPTDefine.OPT_Frame frame, IntPtr pUser)
        {
            // 主动调用回收垃圾 
            // call garbage collection 
            GC.Collect();

            // 控制显示最高帧率为25FPS 
            // control frame display rate to be 25 FPS 
            if (false == IsTimeToDisplay())
            {
                return;
            }

            //HObject Hobj;
            //try
            //{
            //    HOperatorSet.GenImage1(out Hobj, "byte", frame.frameInfo.width, frame.frameInfo.height, frame.pData);
            //}
            //catch (Exception)
            //{
            //    return;
            //}
            Imgdata imgdata = new Imgdata
            {
                data = frame.pData,
                width = (int)frame.frameInfo.width,
                height = (int)frame.frameInfo.height
            };
            ReadImageEvent(imgdata);
        }

        // 判断是否应该做显示操作 
        // calculate interval to determine if it's show time now 
        private bool IsTimeToDisplay()
        {
            m_stopWatch.Stop();
            long m_lDisplayInterval = m_stopWatch.ElapsedMilliseconds;
            if (m_lDisplayInterval <= DEFAULT_INTERVAL)
            {
                m_stopWatch.Start();
                return false;
            }
            else
            {
                m_stopWatch.Reset();
                m_stopWatch.Start();
                return true;
            }
        }

        public override bool Close()
        {
            // 停止拉流 
            // Stop grabbing 
            int res = cam.OPT_StopGrabbing();
            if (res != OPTDefine.OPT_OK)
            {
                return false;
            }


            //关闭相机
            //Close camera 
            res = cam.OPT_Close();
            if (res != OPTDefine.OPT_OK)
            {
                return false;
            }

            // 销毁设备句柄
            // Destroy Device Handle
            res = cam.OPT_DestroyHandle();
            if (res != OPTDefine.OPT_OK)
            {
                return false;
            }

            g_isMainThreadExit = true;

            return true;
        }

        public override bool StartGrab()
        {
            // 开始拉流 
            // Start grabbing 
            return cam.OPT_StartGrabbing() == OPTDefine.OPT_OK;
        }

        public override void StopGrab()
        {
            // 停止拉流 
            // Stop grabbing 
            cam.OPT_StopGrabbing();
        }

        public override void SetTriggerMode(TriggerMode triggerMode)
        {
            // 设置触发模式 
            // Set trigger mode to On 
            cam.OPT_SetEnumFeatureSymbol("TriggerMode", triggerMode.ToString());
        }

        public override void SetTriggerSource(TriggerSource triggerSource)
        {
            string pEnumSymbol;
            switch (triggerSource)
            {
                case TriggerSource.Line1:
                case TriggerSource.Software:
                    pEnumSymbol = triggerSource.ToString();
                    break;
                default:
                    return;
            }
            // 设置触发源为软触发 
            // Set trigger source to Software 
            cam.OPT_SetEnumFeatureSymbol("TriggerSource", pEnumSymbol);
        }

        public override bool TriggerSoftware()
        {
            // 执行软触发
            // Execute soft trigger 
            return cam.OPT_ExecuteCommandFeature("TriggerSoftware") == OPTDefine.OPT_OK;
        }

        public override string GetSerialNumber()
        {
            return camStr;
        }

        public override double GetParameter(string pFeatureName)
        {
            double exposureTimeValue = 0.0;
            // 获取属性值
            // Get feature value 
            int res = cam.OPT_GetDoubleFeatureValue(pFeatureName, ref exposureTimeValue);
            if (res != OPTDefine.OPT_OK)
            {
                return 0;
            }
            return exposureTimeValue;
        }

        public override void SetParameter(string pFeatureName, double doubleValue)
        {
            double exposureMinValue = 0;
            double exposureMaxValue = 0;
            // 获取属性可设的最小值
            // Get property's settable minimum value
            int res = cam.OPT_GetDoubleFeatureMin(pFeatureName, ref exposureMinValue);
            if (res != OPTDefine.OPT_OK)
            {
                return;
            }

            // 获取属性可设的最大值
            // Get property's settable maximum value
            res = cam.OPT_GetDoubleFeatureMax(pFeatureName, ref exposureMaxValue);
            if (res != OPTDefine.OPT_OK)
            {
                return;
            }

            if (doubleValue < exposureMinValue || doubleValue > exposureMaxValue)
            {
                return;
            }

            // 设置属性值
            // Set feature value 
            cam.OPT_SetDoubleFeatureValue(pFeatureName, doubleValue);
        }

        public override void UserSave()
        {
            SaveUserConfiguration();
        }

        private int SaveUserConfiguration()
        {

            //1、选择当前配置为UserSet1
            //1、Select the UserSet1 configuration as the current configuration
            int res = cam.OPT_SetEnumFeatureSymbol("UserSetSelector", "UserSet1");
            if (res != OPTDefine.OPT_OK)
            {
                return res;
            }

            //2、保存配置到UserSet1
            //2、Save configuration to UserSet1
            res = cam.OPT_ExecuteCommandFeature("UserSetSave");

            return res;
        }

        public override void LoadConfigurationFromFile(string fileName)
        {

        }
    }
}
